package com.tianpengtech.front.web.task;

import com.jfinal.kit.PropKit;
import com.jfinal.kit.Ret;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Page;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.ehcache.CacheKit;
import com.sun.org.apache.bcel.internal.generic.IF_ACMPEQ;
import com.tianpengtech.admin.dictionary.DictionaryDao;
import com.tianpengtech.common.exception.ValidateException;
import com.tianpengtech.common.im.kit.PushKit;
import com.tianpengtech.common.ip.IpInfo;
import com.tianpengtech.common.ip.IpUtil;
import com.tianpengtech.common.model.authenticate.Authenticate;
import com.tianpengtech.common.model.dictionary.Dictionary;
import com.tianpengtech.common.model.fair.Fair;
import com.tianpengtech.common.model.moneylog.MoneyLog;
import com.tianpengtech.common.model.task.*;
import com.tianpengtech.common.model.user.User;
import com.tianpengtech.common.search.EqualCondition;
import com.tianpengtech.common.search.LikeCondition;
import com.tianpengtech.common.search.QueryConstructor;
import com.tianpengtech.common.util.DateUtils;
import com.tianpengtech.common.util.ToolRandoms;
import com.tianpengtech.common.util.UAUtil;
import com.tianpengtech.common.validator.Validator;
import com.tianpengtech.common.validator.rules.numberic.MustBeNumberic;
import com.tianpengtech.common.validator.rules.numberic.NumbericMustBeEqual;
import com.tianpengtech.common.validator.rules.numberic.NumbericMustBeGreaterEqualThan;
import com.tianpengtech.common.validator.rules.numberic.NumbericMustBeGreaterThan;
import com.tianpengtech.common.validator.rules.numberic.NumbericMustBeLessEqualThan;
import com.tianpengtech.common.validator.rules.numberic.NumbericMustBeLessThan;
import com.tianpengtech.common.validator.rules.string.StringLengthBetween;
import com.tianpengtech.common.validator.rules.string.StringMustBeRequired;
import com.tianpengtech.front.web.fair.FairService;
import com.tianpengtech.front.web.login.LoginService;
import cz.mallat.uasparser.OnlineUpdater;
import cz.mallat.uasparser.UASparser;
import cz.mallat.uasparser.UserAgentInfo;

import java.util.*;


/**
 * Created by Administrator on 2017/5/31 0031.
 */
public class TaskService {
    private static Task taskDao = Task.dao;
    private static FairService fairService = new FairService();
    private static String TASK_CACHE_CLICK_NAME = "task_click";
    private final Authenticate authDao = Authenticate.dao;
    private final TaskSource taskSourceDao = TaskSource.dao;

    private static String PARAM_TASK_NAME="taskName";
    private static String PARAM_TASK_STATUS="taskStatus";

    private static String PARAM_TASK_STATUS_BEFORE="1"; //未开始
    private static String PARAM_TASK_STATUS_AFTER="2";  //进行中
    private static String PARAM_TASK_STATUS_END="3";    //已完成

    /**
     * 保存任务
     * @param task
     * @throws ValidateException 
     */
    public void save(Task task,String[] source) throws ValidateException{
        
    	int h5_type=task.getInt(Task.H5_TYPE);
    	float price= task.getFloat(Task.TASK_PRICE);
    	int extension_type=task.getInt(Task.EXTENSION_TYPE);
    	String sql="select * from "+Authenticate.dao.tableName()+" where "+Authenticate.USER_ID+" =?";
    	Authenticate auth = Authenticate.dao.findFirst(sql, task.getLong(Task.CREATE_USER));
    	
    	Date start = task.getDate(Task.TASK_START_TIME);
    	Date end = task.getDate(Task.TASK_END_TIME);
    	Validator validator = new Validator();
    	int status = (auth==null)?Authenticate.STATUS_FAILURE:auth.getInt(Authenticate.STATUS);
    	validator.addRule(new NumbericMustBeEqual(status, Authenticate.STATUS_SUCCESS, "当前用户资质认证审核未通过，不允许提交任务"));
    	validator.addRule(new StringLengthBetween(task.getStr(Task.TASK_TITLE),"任务标题不能为空",1,50));
    	validator.addRule(new StringMustBeRequired(DateUtils.formateData(start, DateUtils.YYMMdd_FORMAT),"任务开始时间不能为空"));
    	validator.addRule(new StringMustBeRequired(DateUtils.formateData(end,DateUtils.YYMMdd_FORMAT),"任务结束时间不能为空"));
    	validator.addRule(new NumbericMustBeGreaterEqualThan(end.getTime(),start.getTime(),"任务结束日期必须在开始日期之后"));
    	
    	validator.addRule(new StringMustBeRequired(price+"","任务酬劳不能为空"));
    	validator.addRule(new StringLengthBetween(task.getStr(Task.TASK_DESCRIPTION),"任务描述不能超过400字符",1,400));
    	
    	if(extension_type==Task.EXT_TYPE_ZD){
    		validator.addRule(new NumbericMustBeLessEqualThan(task.getInt(Task.WH_NUMBER),2000,"主播数量不能超过2000个"));
    	}
    	
    	if(h5_type==2){
    		validator.addRule(new NumbericMustBeGreaterThan(source.length,0,"请上传资源图片"));
    	}
    	validator.excute();
    	
    	if (task.getInt(Task.EXTENSION_TYPE)==Task.EXT_TYPE_ZD){
            task.set(Task.STATUS,Task.STATUS_WAIT);
        }else{
            task.set(Task.STATUS,Task.STATUS_APPROVING);
        }
        task.save();
        if (source!=null && source.length>0){
            for (int i=0;i<source.length;i++) {
                String s=source[i];
                TaskSource ts = new TaskSource();
                ts.set(TaskSource.TASK_ID,task.get(Task.ID));
                ts.set(TaskSource.SOURCE,s);
                ts.set(TaskSource.SORT,i+1);
                ts.set(TaskSource.CREATE_DATE,new Date());
                ts.save();
            }
        }
        
    }

    /**
     * 选择完网红后保存
     */
    public Ret saveTaskWait(String[] fairs,String taskId){
        if (!fairService.isExistFair(fairs)){
            return Ret.fail("msg","网红ID不存在");
        }
        for (String id:fairs) {
            if (isExistFairTask(id,taskId)){
                continue;
            }
//            Record record = new Record();
//            record.set(Task.WL_FAIR_ID,id).set(Task.WL_TASK_ID,taskId);
//            Db.save(Task.TASK_WHITELIST,record);
            TaskWh tw= new TaskWh();
            tw.set(TaskWh.WH_ID,id);
            tw.set(TaskWh.TASK_ID,taskId);
            tw.set(TaskWh.CODE,getTaskCode());
            tw.save();
        }
        Task task=taskDao.findById(taskId);
        task.set(Task.STATUS,Task.STATUS_APPROVING);
        task.update();
        return Ret.ok();
    }

    /**
     * 判断网红是否已经领取过此任务
     * @param id
     * @return
     */
    private boolean isExistFairTask(String id,String taskID){
        String key="isExist_"+id+"_"+taskID;
        Boolean f=CacheKit.get(TaskWh.TASKWH_CACHE_NAME,key);
        if (f!=null){
            return f;
        }
        String sql = "select tw.id from "+TaskWh.dao.tableName()+" tw  where "+TaskWh.TASK_ID+ "=? and "+TaskWh.WH_ID+"=? and tw."+TaskWh.DELETETAG+"="+TaskWh.DELETE_STATUS_NO;
        List<TaskWh> list=TaskWh.dao.find(sql,new Object[]{taskID,id});
        if (list.size()>0){
            return true;
        }else{
            return false;
        }
    }


    /**
     * 点击任务链接保存
     * @param ref
     * @param ua
     * @param ip
     */
    public void saveTaskClick(String ref, String ua ,String ip,String code){
        synchronized (code) {
            TaskWh taskWh = getByCode(code);
            boolean devModel = PropKit.getBoolean("devMode");
            //如果是测试环境
            if (!devModel) {
                Object i = CacheKit.get(TASK_CACHE_CLICK_NAME, ip + taskWh.get(TaskWh.ID));
                //判断在缓存有效期内是否点击过
                if (i != null) {
                    return;
                }
            }
            UserAgentInfo userAgentInfo = UAUtil.get(ua);
            IpInfo info = IpUtil.getIpInfo(ip);
            TaskCount taskCount = new TaskCount();
            taskCount.set(TaskCount.TASK_ID, taskWh.get(TaskWh.TASK_ID));
            taskCount.set(TaskCount.WH_ID, taskWh.get(TaskWh.WH_ID));
            taskCount.set(TaskCount.URL, ref);
            taskCount.set(TaskCount.IP, ip);
            taskCount.set(TaskCount.TASK_CODE, code);
            taskCount.set(TaskCount.USER_AGENT, ua);
            if (userAgentInfo != null) {
                taskCount.set(TaskCount.OS_NAME, userAgentInfo.getOsName());
                taskCount.set(TaskCount.UA_NAME, userAgentInfo.getUaName());
                taskCount.set(TaskCount.DEVICE_TYPE, userAgentInfo.getDeviceType());
                taskCount.set(TaskCount.REQ_TYPE, userAgentInfo.getType());
            }
            if (info != null) {
                taskCount.set(TaskCount.COUNTRY, info.getCountry());
                taskCount.set(TaskCount.PART, info.getPart());
                taskCount.set(TaskCount.PROVINCE, info.getProvince());
                taskCount.set(TaskCount.CITY, info.getCity());
            }
            taskCount.save();
            //缓存内写入数据防止此IP在限制时间内再次点击
            CacheKit.put(TASK_CACHE_CLICK_NAME, ip + taskWh.get(TaskWh.ID), 1);
            //点击次数加一
            int num = taskWh.get(TaskWh.CLICK_NUM);
            taskWh.set(TaskWh.CLICK_NUM, ++num);
            taskWh.update();
        }
    }


    /**
     * 点击任务链接保存
     * @param ref
     * @param ua
     * @param ip
     */
    public void saveTaskCvs(String ref, String ua ,String ip,String code){
        synchronized (code) {
            TaskWh taskWh = getByCode(code);
            boolean devModel = PropKit.getBoolean("devMode");
            //如果是测试环境
            if (!devModel) {
                Object i = CacheKit.get(TASK_CACHE_CLICK_NAME, ip + taskWh.get(TaskWh.ID));
                //判断在缓存有效期内是否点击过
                if (i != null) {
                    return;
                }
            }
            UserAgentInfo userAgentInfo = UAUtil.get(ua);
            IpInfo info = IpUtil.getIpInfo(ip);
            TaskCVS taskCvs = new TaskCVS();
            taskCvs.set(TaskCount.TASK_ID, taskWh.get(TaskWh.TASK_ID));
            taskCvs.set(TaskCount.WH_ID, taskWh.get(TaskWh.WH_ID));
            taskCvs.set(TaskCount.URL, ref);
            taskCvs.set(TaskCount.IP, ip);
            taskCvs.set(TaskCount.TASK_CODE, code);
            taskCvs.set(TaskCount.USER_AGENT, ua);
            if (userAgentInfo != null) {
                taskCvs.set(TaskCount.OS_NAME, userAgentInfo.getOsName());
                taskCvs.set(TaskCount.UA_NAME, userAgentInfo.getUaName());
                taskCvs.set(TaskCount.DEVICE_TYPE, userAgentInfo.getDeviceType());
                taskCvs.set(TaskCount.REQ_TYPE, userAgentInfo.getType());
            }
            if (info != null) {
                taskCvs.set(TaskCount.COUNTRY, info.getCountry());
                taskCvs.set(TaskCount.PART, info.getPart());
                taskCvs.set(TaskCount.PROVINCE, info.getProvince());
                taskCvs.set(TaskCount.CITY, info.getCity());
            }
            taskCvs.save();
            //缓存内写入数据防止此IP在限制时间内再次点击
            CacheKit.put(TASK_CACHE_CLICK_NAME, ip + taskWh.get(TaskWh.ID), 1);
            //点击次数加一
            int num = taskWh.get(TaskWh.CVS_NUM);
            taskWh.set(TaskWh.CVS_NUM, ++num);
            taskWh.update();
        }
    }



    /**
     * 获取唯一Code
     * @return
     */
    private String getTaskCode(){
        String code=ToolRandoms.getUuid(true);
        TaskWh record=TaskWh.dao.findFirstByCache(Task.TASK_CACHE_NAME,code,"select * from "+TaskWh.dao.tableName() + " where code=?",code);
        if (record==null) {
            CacheKit.put(Task.TASK_CACHE_NAME,code,record);
            return code;
        }else{
            return getTaskCode();
        }
    }


    /**
     * 根据Code 获取值
     * @return
     */
    public TaskWh getByCode(String code){
        TaskWh record=TaskWh.dao.findFirstByCache(Task.TASK_CACHE_NAME,code,"select * from "+TaskWh.dao.tableName() + " where code=?",code);
        return record;
    }


    /**
     * 分页查询
     * @param pageNum
     * @param length
     * @param params
     * @return
     */
    public Page<Task> task(int pageNum, int length, Map<String,Object> params){
        List<Object> param=new ArrayList<>();
        String s = "select *,task.status as status,task.id as id ";
        StringBuffer sql= new StringBuffer(" from " + taskDao.tableName() + " task left join " + TaskWh.dao.tableName() + " wh on task." + Task.ID + "=wh." + TaskWh.TASK_ID +" left join "+Fair.dao.tableName()+" fair on fair."+Fair.ID+"=wh."+TaskWh.WH_ID);
        sql.append(" where task." + Task.DELETETAG+"=? and task."+Task.CREATE_USER+"=? and task."+Task.STATUS+"!="+Task.STATUS_WAIT );
        param.add(Task.DELETE_STATUS_NO);
        param.add(params.get("user"));
        if (params!=null) {
            Object taskName = params.get(PARAM_TASK_NAME);
            Object taskStatus = params.get(PARAM_TASK_STATUS);
            if (taskName!=null && StrKit.notBlank(taskName.toString())) {
                sql.append(" and (");
                sql.append("task." + Task.TASK_TITLE+" like ? or ");
                param.add("%" + taskName.toString() + "%");
                sql.append("fair." + Fair.NICK_NAME+" like ?)");
                param.add("%" + taskName.toString() + "%");
            }
            if(taskStatus!=null && StrKit.notBlank(taskStatus.toString())){
                sql.append(" and (");
                if (taskStatus.toString().equals(PARAM_TASK_STATUS_BEFORE)){
                    sql.append("task." + Task.STATUS+"=? and task."+Task.TASK_START_TIME+">?)");
                    param.add(Task.STATUS_SUCCESS);
                    param.add(new Date());
                }else if(taskStatus.toString().equals(PARAM_TASK_STATUS_AFTER)){
                    sql.append("task." + Task.STATUS+"=? and task."+Task.TASK_START_TIME+"<?)");
                    param.add(Task.STATUS_SUCCESS);
                    param.add(new Date());
                }else if(taskStatus.toString().equals(PARAM_TASK_STATUS_END)){
                    sql.append("task." + Task.STATUS+"=?)");
                    param.add(Task.STATUS_COMPLETED);
                }
            }
            sql.append(" group by task."+Task.ID+" order by task."+Task.ID+" DESC");
        }
        Page<Task> page=taskDao.paginate(pageNum,length,s,sql.toString(),param.toArray());
        List<Task> tasks = page.getList();
        for (Task t:tasks) {
            t.put("click",t.getClick());
            t.put("cvs",t.getCvs());
            t.put("status",t.status());
        }
        return page;
    }


    /**
     * 根据网红Id获取相关任务信息
     * @param fairId
     * @return
     */
    public Page<Task> findTaskByFair(int pageNum, int length, int fairId){
        String sql="select * ";
        QueryConstructor queryConstructor = new QueryConstructor();
        queryConstructor.setCommand("from "+TaskWh.dao.tableName() +" tw left join " + taskDao.tableName() +" task on tw."+TaskWh.TASK_ID+"=task."+Task.ID);
        queryConstructor.and(new EqualCondition("tw." + TaskWh.DELETETAG, TaskWh.DELETE_STATUS_NO));
        queryConstructor.and(new EqualCondition("tw." + TaskWh.WH_ID,fairId));
        String from = queryConstructor.buildSQL("order by tw.id desc");
        return taskDao.paginateByCache(Task.TASK_CACHE_NAME,"fair_task_"+fairId+"_"+pageNum+"_"+length,pageNum,length,sql,from,queryConstructor.getParams().toArray());
    }

    /**
     * 根据ID查询任务详情
      * @param id
     * @return
     */
    public Task findTaskById(String id){
        return taskDao.findById(id);
    }

    /**
     * 获取所有停止的任务信息
     * @return
     */
    public List<Task> findStopTask(){
        String sql = "select "+Task.ID+","+Task.TASK_PRICE+","+Task.TASK_TITLE+" from "+taskDao.tableName() + " where to_days("+Task.TASK_END_TIME+")<=to_days(now())-1 and "+Task.STATUS +"!="+Task.STATUS_COMPLETED;
        return taskDao.find(sql);
    }

    /**
     * 判断是否可以创建任务
     * @return
     */
    public Authenticate isCreate(long userId){
        Authenticate auth = authDao.findFirst("select * from fair_user_authenticate where user_id=?",userId);
//        if (auth==null){
//            return false;
//        }else if (auth.getInt(Authenticate.STATUS)==Authenticate.STATUS_SUCCESS){
//            return true;
//        }else{
//            return false;
//        }
        return auth;
    }
    
    /**
     * 获取指定任务数据的价格列表
     * @return
     */
    public List<Dictionary> getPriceList(){
    	return DictionaryDao.ME.readParents(Dictionary.CONST_PRICE_CODE);
    }


    /**
     * 获取任务资源
     * @param taskId
     * @return
     */
    public List<TaskSource> findSourceByTask(int taskId){
        String sql = String.format("select * from %s where %s=? and %s=? order by %s asc",taskSourceDao.tableName(),TaskSource.DELETETAG,TaskSource.TASK_ID,TaskSource.SORT);
        return taskSourceDao.find(sql,TaskSource.DELETE_STATUS_NO,taskId);
    }

    /**
     * 保存排序
     */
    public void saveTaskSource(Map<String,String> sources){
        sources.keySet().forEach(str -> {
            TaskSource ts = new TaskSource();
            ts.set(TaskSource.ID,str);
            ts.set(TaskSource.SORT,sources.get(str));
            ts.update();
        });
    }


    /**
     * 定时任务，定时关闭任务
     */
    public void taskJob(){
        List<Task> tasks = findStopTask();
        for (Task task: tasks) {
            task.set(Task.STATUS,Task.STATUS_COMPLETED);
            final Float price=task.getFloat(Task.TASK_PRICE);
            List<Fair> fairs=fairService.findByTaskJob(task.getLong(Task.ID)+"");
            for (Fair f:fairs) {
                Double d = f.get(Fair.MONEY);
                if (d==null){
                    d=0D;
                }
                double sum=d.doubleValue()+price.doubleValue();
                f.set(Fair.MONEY,sum);
                f.update();
                MoneyLog ml = new MoneyLog();
                ml.set(MoneyLog.WH_ID,f.get(Fair.ID));
                ml.set(MoneyLog.OPERID,task.getLong(Task.ID));
                ml.set(MoneyLog.STATE, MoneyLog.STATE_ADD);
                ml.set(MoneyLog.TYPE,MoneyLog.TYPE_RENWU);
                ml.set(MoneyLog.MONEY,price.doubleValue());
                ml.set(MoneyLog.DESCRIPTION,"任务完成："+task.getStr(Task.TASK_TITLE));
                ml.save();
            }
            task.update();
        }
    }
}
